/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ceair.flight.refund.service.cronjob.autocheck.impl;

import com.ceair.flight.refund.dto.appmoblie.RefundApplyDto;
import com.ceair.flight.refund.dto.appmoblie.RefundTktDto;
import com.ceair.flight.refund.location.dao.IPayDao;
import com.ceair.flight.refund.location.dt.enums.PayResponseCodeEnum;
import com.ceair.flight.refund.location.dt.enums.RefundReasonEnum;
import com.ceair.flight.refund.location.dt.enums.RefundStatusEnum;
import com.ceair.flight.refund.location.model.PayDO;
import com.ceair.flight.refund.location.model.PayProductDO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 *
 * @author youguilin
 */
@Service("userRefusePayChecker")
@Order(value = 2)
public class RefusePayAndRiskFailChecker extends BaseAutoChecker {

    private static final Logger LOG = LoggerFactory.getLogger(RefusePayAndRiskFailChecker.class);
    @Autowired
    private IPayDao payDao;

    public RefusePayAndRiskFailChecker() {
        super("userRefusePayChecker");
    }

    @Override
    public boolean autoCheck(RefundApplyDto refundApply) {
        if (!isValidStatus(refundApply)) {
            LOG.info("Refund apply status is not valid for auto audit");
            return false;
        }
        LOG.debug("Checking refund apply {} if it is risk fail or user refuse pay", refundApply.getId());
        RefundTktDto refundTkt = refundApply.getRefundTkt();
        String orderNo = refundTkt.getOrderNo();
        String flightOrderNo = refundTkt.getFlightOrderNo();
        RefundReasonEnum reasonEnum = super.getRefundReason(refundApply);
        //用户拒付
        if (RefundReasonEnum.USER_REFUSE_PAY == reasonEnum) {
            LOG.info("Refund apply {} apply reason is {}", refundApply.getId(), RefundReasonEnum.USER_REFUSE_PAY);
            return checkPayStatus(orderNo, flightOrderNo, PayResponseCodeEnum.RISK_FAILURE_NO_REFUND_PAY);
        } else if (RefundReasonEnum.RISK_CHECK_FAILED == reasonEnum) {
            LOG.info("Refund apply {} apply reason is {}", refundApply.getId(), RefundReasonEnum.RISK_CHECK_FAILED);
            return checkPayStatus(orderNo, flightOrderNo, PayResponseCodeEnum.RISK_FAILURE);
        }
        return goNextOrReturn(refundApply);
    }

    private boolean isValidStatus(final RefundApplyDto refundApply) {
        String statusCode = refundApply.getStatus();
        if (statusCode == null || statusCode.isEmpty()) {
            LOG.warn("Unknow refund apply status, stop auto audit checking");
            return false;
        }
        RefundStatusEnum refundStatusEnum = RefundStatusEnum.getByCode(statusCode);
        LOG.info("Refund apply status is {}", refundStatusEnum);
        return RefundStatusEnum.WAIT_FIRST_AUDIT == refundStatusEnum;
    }

    private boolean checkPayStatus(String orderNo, String flightOrderNo, PayResponseCodeEnum codeEnum) {
        Set<PayDO> pays = payDao.getPayListByOrderNo(orderNo);
        Set<PayDO> flightOrderPays = getFlightOrderPay(pays, flightOrderNo);
        if (flightOrderPays == null || flightOrderPays.isEmpty()) {
            LOG.warn("No payment record found for flight order {}", flightOrderNo);
            return false;
        }
        for (PayDO pay : flightOrderPays) {
            LOG.info("Flight order {} payment response code {}", flightOrderNo, pay.getRespCode());
            boolean isValid = codeEnum == PayResponseCodeEnum.getByCode(pay.getRespCode());
            if (isValid) {
                return true;
            }
        }
        return false;
    }

    private Set<PayDO> getFlightOrderPay(Set<PayDO> pays, String flightOrderNo) {
        if (pays == null || pays.isEmpty()) {
            return Collections.EMPTY_SET;
        }
        Set<PayDO> result = new HashSet<>(pays.size(), 1.0f);
        for (PayDO pay : pays) {
            Set<PayProductDO> products = pay.getPayProducts();
            if (products == null || products.isEmpty()) {
                LOG.warn("Pay products size is empty");
                continue;
            }
            for (PayProductDO product : products) {
                String productId = product.getProductId();
                if (flightOrderNo.equals(productId)) {
                    result.add(pay);
                }
            }
        }
        return result;
    }
}
